package com.jrx.anytxn.investor.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanUtils;
import com.jrx.anytxn.investor.bean.InvestorTransferBean;
import com.jrx.anytxn.investor.bean.InvestorTransferSaveBean;
import com.jrx.anytxn.investor.constant.TransBizConstant;
import com.jrx.anytxn.investor.entity.AmInterestAccrualInvestorInfo;
import com.jrx.anytxn.investor.entity.TlGlInterfaceInvestorInfo;
import com.jrx.anytxn.investor.entity.TlInvestorLoanChange;
import com.jrx.anytxn.investor.service.IInvestorAccountService;
import com.jrx.anytxn.investor.service.IInvestorGlInterfaceService;
import com.jrx.anytxn.investor.service.IInvestorLoanChangeService;
import com.jrx.anytxn.investor.service.IInvestorTransferTypeStrategy;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.transaction.bean.DelqAccountBean;
import com.jrx.anytxn.transaction.bean.DelqClassifyBean;
import com.jrx.anytxn.transaction.bean.DelqNonAccrualBean;
import com.jrx.anytxn.transaction.bean.DelqParamBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.Date;
import java.util.Optional;

/**
 * 累计账户转列策略
 * 
 * @author liuyang
 * @date 2020-05-27
 **/
@Service
public class InvestorAccuAcctTransferTypeStrategy implements IInvestorTransferTypeStrategy<AmInterestAccrualInvestorInfo> {
    
    private static final Logger logger = LoggerFactory.getLogger(InvestorAccuAcctTransferTypeStrategy.class);

    @Autowired
    private IInvestorGlInterfaceService glInterfaceService;
    @Autowired
    private IInvestorLoanChangeService loanChangeService;
    @Autowired
    private IInvestorAccountService accountService;

    /**
     * 累计账户外转列处理 会计状态升级，转表外，五级分类升级
     *
     * @param transferBean 转列辅助Bean
     * @return InvestorTransferSaveBean 转列保存Bean
     * @throws TxnException
     * @author liuyang
     * @date 2020-05-27
     */
    @Override
    public InvestorTransferSaveBean transferOut(InvestorTransferBean<AmInterestAccrualInvestorInfo> transferBean) throws TxnException {
        AmInterestAccrualInvestorInfo accuAcct =  transferBean.getTransferObject();
        logger.info("累计账户外转列accuAcct:{}",BeanUtils.toMap(accuAcct));
        DelqParamBean delqParamBean = transferBean.getDelqParamBean();
        Date bussinessDate = transferBean.getBussinessDate();
        int accountingDays = transferBean.getAccountingDays();
        int nonAccrualDays = transferBean.getNonAccrualDays();
        int classifyDays = transferBean.getClassifyDays();
        InvestorTransferSaveBean transferSaveBean = new InvestorTransferSaveBean();
        AmInterestAccrualInvestorInfo updateAccuAcct = new AmInterestAccrualInvestorInfo();
        updateAccuAcct.setId(accuAcct.getId());
        updateAccuAcct.setCustomerId(accuAcct.getCustomerId());
        updateAccuAcct.setTenantId(accuAcct.getTenantId());
        String tempAccountStatus = accuAcct.getAccountingPhase();
        boolean isUpdate = false;

        //五级分类
        String classify = delqParamBean.getDelqClassifyBeanList().stream()
                .filter(bean -> classifyDays >= bean.getClassifyDays())
                .map(DelqClassifyBean::getClassifyType)
                .max(String::compareTo)
                .orElse("0");

        //如果与原状态不同则修改
        if (!classify.equals(accuAcct.getLoanClassify())) {
            isUpdate = true;
            updateAccuAcct.setLoanClassify(classify);
            accuAcct.setLoanClassify(classify);
        }

        //会计状态转列处理，获取转列天数小于延滞天数，取会计状态最大的那个
        DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                .filter(bean -> bean.getAccountType().contains(accuAcct.getAccountType()))
                .filter(bean -> accountingDays >= bean.getTransferDays())
                .max(Comparator.comparing(DelqAccountBean::getAccountingPhase))
                .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));

        String accountingPhase = delqAccountBean.getAccountingPhase();
        logger.info("会计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqAccountBean), accountingPhase);
        //如果允许转列
        if (TransBizConstant.TRANSFER_FLAG_1.equals(delqAccountBean.getTransferFlag()) &&
                !tempAccountStatus.equals(accountingPhase)) {
            isUpdate = true;
            String txnCode = delqAccountBean.getTxnCode();
            String eventCode = delqAccountBean.getEventCode();
            updateAccuAcct.setAccountingPhase(accountingPhase);
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(accuAcct, accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
            logger.info("会计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(accuAcct.getAccountType(),accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()),eventCode,tempAccountStatus,accountingPhase);
            transferSaveBean.getLoanChangeList().add(loanChange);
        }

        //应计/非应计，根据交易账户类型获取对应的参数
        DelqNonAccrualBean delqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(accuAcct.getAccountType());
        logger.info("应计/非应计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqNonAccrualBean), accuAcct.getNonAccrualsFlag());
        //延滞天数>=转列天数 && 允许转列
        if (nonAccrualDays >= delqNonAccrualBean.getTransDays() &&
                TransBizConstant.TRANSFER_FLAG_1.equals(delqNonAccrualBean.getNonAccrualFlag()) &&
                TransBizConstant.NON_ACCRUALS_FLA_0.equals(accuAcct.getNonAccrualsFlag())) {
            isUpdate = true;
            String txnCode = delqNonAccrualBean.getNonTxnCode();
            String taxTxnCode = delqNonAccrualBean.getNonTaxTxnCode();
            updateAccuAcct.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_1);
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(accuAcct, accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
            TlGlInterfaceInvestorInfo taxGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(accuAcct, accuAcct.getTaxAmt(), taxTxnCode, tempAccountStatus, bussinessDate);
            logger.info("应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
            logger.info("税金应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(taxGlInterfaceInfo));
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));
            Optional.ofNullable(taxGlInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(accuAcct.getAccountType(),accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()),TransBizConstant.EVENT_CODE_TN,TransBizConstant.NON_ACCRUALS_FLA_A,TransBizConstant.NON_ACCRUALS_FLA_N);
            transferSaveBean.getLoanChangeList().add(loanChange);

            //1.生成表外累计账户
            AmInterestAccrualInvestorInfo nonAccuAcct = accountService.castNonInterestAccrualAccount(accuAcct,bussinessDate);
            transferSaveBean.setSaveAccuAcct(nonAccuAcct);
            //2.更新累计账户的stop_accrual_flag停止计息标志为1-停止计息
            updateAccuAcct.setStopAccrualFlag(TransBizConstant.STOP_ACCRU_FLAG_1);
            //3.若为利息累计账户，更新max_interest最大利息金额为当前accrual_total_accru_interest已累计总利息。
            if(TransBizConstant.INTEREST_ACCRUAL_TYPE_66.equals(accuAcct.getAccountType())){
                updateAccuAcct.setMaxInterest(accuAcct.getAccrualTotalAccruInterest());
            }
        }

        if (isUpdate) {
            transferSaveBean.setUpdateAccuAcct(updateAccuAcct);
            return transferSaveBean;
        }
        return null;
    }

    /**
     * 累计账户内转列出处理 会计状态降级，转应计，五级分类降级
     *
     * @param transferBean 转列辅助Bean
     * @return InvestorTransferSaveBean 转列保存Bean
     * @throws TxnException
     * @author liuyang
     * @date 2020-05-27
     */
    @Override
    public InvestorTransferSaveBean transferIn(InvestorTransferBean<AmInterestAccrualInvestorInfo> transferBean) throws TxnException {
        AmInterestAccrualInvestorInfo accuAcct =  transferBean.getTransferObject();
        logger.info("累计账户内转列accuAcct:{}",BeanUtils.toMap(accuAcct));
        DelqParamBean delqParamBean = transferBean.getDelqParamBean();
        Date bussinessDate = transferBean.getBussinessDate();
        int accountingDays = transferBean.getAccountingDays();
        int nonAccrualDays = transferBean.getNonAccrualDays();
        int classifyDays = transferBean.getClassifyDays();
        InvestorTransferSaveBean transferSaveBean = new InvestorTransferSaveBean();
        AmInterestAccrualInvestorInfo updateAccuAcct = new AmInterestAccrualInvestorInfo();
        updateAccuAcct.setId(accuAcct.getId());
        updateAccuAcct.setCustomerId(accuAcct.getCustomerId());
        updateAccuAcct.setTenantId(accuAcct.getTenantId());
        String tempAccountStatus = accuAcct.getAccountingPhase();
        boolean isUpdate = false;

        //五级分类
        String classify = delqParamBean.getDelqClassifyBeanList().stream()
                .filter(bean -> classifyDays >= bean.getClassifyDays())
                .map(DelqClassifyBean::getClassifyType)
                .max(String::compareTo)
                .orElse("0");

        //如果与原状态不同则修改
        if (!classify.equals(accuAcct.getLoanClassify())) {
            isUpdate = true;
            updateAccuAcct.setLoanClassify(classify);
            accuAcct.setLoanClassify(classify);
        }

        //会计状态转列处理，获取转列天数小于延滞天数并且允许转列的参数，取会计状态最大的那个
        DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                .filter(bean -> bean.getAccountType().contains(accuAcct.getAccountType()))
                .filter(bean -> accountingDays >= bean.getTransferDays())
                .filter(bean -> TransBizConstant.TRANSFER_FLAG_1.equals(bean.getTransferFlag()))
                .max(Comparator.comparing(DelqAccountBean::getAccountingPhase))
                .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));

        String accountingPhase = delqAccountBean.getAccountingPhase();
        logger.info("会计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqAccountBean), accountingPhase);
        if (!tempAccountStatus.equals(accountingPhase)) {
            isUpdate = true;
            String txnCode = delqAccountBean.getTxnCode();
            String eventCode = delqAccountBean.getEventCode();
            updateAccuAcct.setAccountingPhase(accountingPhase);
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(accuAcct, accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
            logger.info("会计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(accuAcct.getAccountType(),accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()),eventCode,tempAccountStatus,accountingPhase);
            transferSaveBean.getLoanChangeList().add(loanChange);
        }

        //应计/非应计，根据交易账户类型获取对应的参数
        DelqNonAccrualBean delqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(accuAcct.getAccountType());
        logger.info("应计/非应计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqNonAccrualBean), accuAcct.getNonAccrualsFlag());
        //延滞天数<转列天数 && 允许转列
        if (nonAccrualDays < delqNonAccrualBean.getTransDays() &&
                TransBizConstant.NON_ACCRUALS_FLA_1.equals(accuAcct.getNonAccrualsFlag())) {
            isUpdate = true;

            // 表外累计的转回表内 交易码转为T58XXX
            String txnCode = delqNonAccrualBean.getInNonTxnCode();
            String taxTxnCode = delqNonAccrualBean.getInNonTxnCode();

            //表内累计的转表外后转回表内 交易码转为T56XXX
            if("5".equals(accuAcct.getTxnCode().substring(1,2))){
                txnCode = txnCode.substring(0,1)+(Integer.parseInt(txnCode.substring(1))-2000);
                taxTxnCode = taxTxnCode.substring(0,1)+(Integer.parseInt(taxTxnCode.substring(1))-2000);
            }
            updateAccuAcct.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_0);
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(accuAcct, accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
            TlGlInterfaceInvestorInfo taxGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(accuAcct, accuAcct.getTaxAmt(), taxTxnCode, tempAccountStatus, bussinessDate);
            logger.info("应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
            logger.info("税金应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(taxGlInterfaceInfo));
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));
            Optional.ofNullable(taxGlInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(accuAcct.getAccountType(),accuAcct.getAccrualTotalAccruInterest().subtract(accuAcct.getTaxAmt()),TransBizConstant.EVENT_CODE_TA,TransBizConstant.NON_ACCRUALS_FLA_N,TransBizConstant.NON_ACCRUALS_FLA_A);
            transferSaveBean.getLoanChangeList().add(loanChange);
        }

        if (isUpdate) {
            transferSaveBean.setUpdateAccuAcct(updateAccuAcct);
            return transferSaveBean;
        }
        return null;
    }
}
